#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>

#define X 0
#define Y 1

struct acc{
  float x;
  float y;
};

struct speed{
  float x;
  float y;
};

struct body{
  float m;
  float x;
  float y;
  struct speed * speed;
  struct acc * new_acc;
};

float dst(struct body * a, struct body * b)
{
  return sqrt(((a->x-b->x)*(a->x-b->x) + (a->y-b->y)*(a->y-b->y))); 
}

float unit(int dir, struct body * a, struct body * b)
{
  if(dir == X)
    {
      float length = (b->x - a->x);
      return (length/dst(a,b));
    }
  else
    {
      float length = (b->y - a->y);
      return (length/dst(a,b));
    }
}

void print(struct body ** bodies, int nb_bodies)
{
  int i;
  for(i=0 ; i<nb_bodies ; i++)
    {
      printf("%d %f %f\n",i,bodies[i]->x,bodies[i]->y);
    }
  printf("\n");
}

struct body ** parse(char * path)
{
  FILE * fd = fopen(path,"r");
  int nb_all;
  int nb_bodies;
  fscanf(fd,"%d %d",&nb_all,&nb_bodies);
  struct body ** bodies = malloc(nb_all*sizeof(struct body *));
  int j;
  
  /* while(i<(rank*(*nb_bodies))) */
/*     { */
/*       fscanf(fd,"%f %f %f %f %f",&ligne[0],&ligne[1],&ligne[2],&ligne[3],&ligne[4]); */
/*       i++; */
/*     } */
  
  for (j=0 ; j<nb_all ; j++){
    bodies[j] = malloc(sizeof(struct body));
    bodies[j]->speed = malloc(sizeof(struct speed));
    bodies[j]->new_acc = malloc(sizeof(struct acc));
    fscanf(fd,"%f %f %f %f %f\n",&bodies[j]->m,&bodies[j]->x,&bodies[j]->y,
	   &bodies[j]->speed->x,&bodies[j]->speed->y);  
  }
  return bodies;
  fclose(fd);
}


int main(int argc, char * argv[])
{
  if(argc<5)
    {
      printf("utilisation : %s nbre_de_masses nbre_de_tours delta_T file.data\n",argv[0]);
      return 0;
    }
  srand(time(NULL));
  int nb_bodies = atoi(argv[1]);
  int max_run = atoi(argv[2]);
  float dt = atof(argv[3]);
  char * path = argv[4];
  float G = 6.67384*pow(10,-11);
  int nb;
  struct body ** bodies = parse(path);
  int i,k=0,j=0;
  //initialisation des masses

  //  print(bodies,nb_bodies);
  while(k<max_run)
    {
      //calcul des forces.
      for(i=0 ; i<nb_bodies ; i++)
	{
	  //calcul des forces sur 1 masse.
	  struct acc * result = malloc(sizeof(struct acc));
	  result->x = 0;
	  result->y = 0;
	  for (j=0 ; j<nb_bodies ; j++)
	    {
	      if(i!=j)
		{
		  float dist = dst(bodies[i],bodies[j]);
		  float f = G*(bodies[i]->m*bodies[j]->m)/(dist*dist);
		  //printf("unitx : %f, unity : %f\n",unit(X,bodies[i],bodies[j]),unit(Y,bodies[i],bodies[j]));
		  result->x += f*unit(X,bodies[i],bodies[j]);
		  result->y += f*unit(Y,bodies[i],bodies[j]);
		}
	
	    }
	  bodies[i]->new_acc = result;
	  //printf("resultante : %f %f\n",result->x,result->y);
	}
      //application des accelerations aux masses.
      for(j=0 ; j<nb_bodies ; j++)
	{
	  //vitesse
	  bodies[j]->x += dt*bodies[j]->speed->x + bodies[j]->new_acc->x*dt*dt/(2*bodies[j]->m); 
	  bodies[j]->y += dt*bodies[j]->speed->y + bodies[j]->new_acc->y*dt*dt/(2*bodies[j]->m); 
	  bodies[j]->speed->x += (bodies[j]->new_acc->x/bodies[j]->m)*dt;
	  bodies[j]->speed->y += (bodies[j]->new_acc->y/bodies[j]->m)*dt;
	  free(bodies[j]->new_acc);
	}
      k++;
      print(bodies,nb_bodies);
    }
  //TODO free
  
  return 0;
}
